home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / mac / hypercrd / xcmd / dxcmds34.sit / Dartmouth XCMD's 3.4.3 / card_18515.txt < prev    next >
Text File  |  1990-04-17  |  20KB  |  592 lines

  1. -- card: 18515 from stack: in.3
  2. -- bmap block id: 0
  3. -- flags: 4000
  4. -- background id: 3241
  5. -- name: DeleteResFork
  6. ----- HyperTalk script -----
  7. on Install
  8.   get ChooseTargetStack()
  9.   InstallResource XCMD,DeleteResFork,it
  10. end Install
  11.  
  12.  
  13. -- part 3 (button)
  14. -- low flags: 00
  15. -- high flags: A003
  16. -- rect: left=64 top=300 right=322 bottom=202
  17. -- title width / last selected line: 0
  18. -- icon id / first selected line: 0 / 0
  19. -- text alignment: 1
  20. -- font id: 0
  21. -- text size: 12
  22. -- style flags: 0
  23. -- line height: 16
  24. -- part name: DeleteResFork
  25. ----- HyperTalk script -----
  26. on mouseUp
  27.   -- This button uses the DeleteResFork XCMD to delete the
  28.   -- resource fork of a stack.
  29.   deleteresfork
  30.   get the result
  31.   if it is not empty then put it
  32. end mouseUp
  33.  
  34.  
  35.  
  36. -- part 4 (field)
  37. -- low flags: 81
  38. -- high flags: 2007
  39. -- rect: left=12 top=26 right=298 bottom=491
  40. -- title width / last selected line: 0
  41. -- icon id / first selected line: 0 / 0
  42. -- text alignment: 0
  43. -- font id: 22
  44. -- text size: 10
  45. -- style flags: 0
  46. -- line height: 13
  47. -- part name: Source
  48.  
  49.  
  50. -- part 6 (button)
  51. -- low flags: 00
  52. -- high flags: A003
  53. -- rect: left=299 top=300 right=322 bottom=438
  54. -- title width / last selected line: 0
  55. -- icon id / first selected line: 0 / 0
  56. -- text alignment: 1
  57. -- font id: 0
  58. -- text size: 12
  59. -- style flags: 0
  60. -- line height: 16
  61. -- part name: Show Pascal Source
  62. ----- HyperTalk script -----
  63. on mouseUp
  64.   set the visible of card field 1 to not the visible of card field 1
  65.   if the visible of card field 1 is true then
  66.     set the name of me to "Hide Pascal Source"
  67.   else set the name of me to "Show Pascal Source"
  68. end mouseUp
  69.  
  70.  
  71.  
  72. -- part contents for background part 16
  73. ----- text -----
  74. DELETERESFORK XCMD version 1.6
  75. Kevin Calhoun
  76.  
  77. DeleteResFork deletes the resource fork of a stack while leaving the data fork intact.
  78.  
  79. Each Macintosh file, including HyperCard stacks, has two forks--a resource fork and a data fork, either of which may be empty.  HyperCard stores all the information about buttons, fields, text, and pictures in the data fork of your stacks.  XCMD's, XFCN's, PICT's, and other resources are stored in the resource fork.
  80.  
  81. DeleteResFork is for that trying moment when you discover that the resource fork of a stack has been ruined.  If this should occur, all of the data HyperCard relies on will still be intact--it's stored in the data fork--but you'll need to jettison your garbled resource fork and then re-install the necessary resources.
  82.  
  83. How can you tell if the resource fork has been ruined?  If ResEdit tells you that there was an error while opening the stack or if a disk utility tells you that the resource fork still takes up disk space even though HyperCard can't find the resources, then you know that your resource fork has been compromised.  (Sometimes HyperCard can't find newly copied resources until you close the stack and then reopen it.  Don't panic until after you've tried this.)
  84.  
  85. DeleteResFork won't let you regain access to a ruined resource fork.  Instead, it just gets rid of it.  It lets you "shake loose" a worthless resource fork that can't be read and start afresh.
  86.  
  87. NOTE:  It's unwise to delete the resource fork of a stack that is already open.  Make a copy of the stack and then work on the copy.
  88.  
  89. INVOKING DELETERESFORK
  90.  
  91. DeleteResFork <"fileName">
  92.  
  93. DeleteResFork takes one optional parameter, the full pathname of the file whose resource fork you want to delete.  If the file name is not supplied, a standard file dialog box appears, from which you can select a stack.
  94.  
  95. If the file name supplied is not the full pathname of an extant stack, or if there is any other error, DeleteResFork will return an error message as the Result.  The first word of this message will be "Error."
  96.  
  97. NOTE FOR ADVANCED PROGRAMMERS:
  98. Because XCMD's have no "owned resources" and because there's no official "XCMD Mover," you can never count on resources such as DITL's or STR#'s being around when you need them.  The PrintField XCMD checks for the presence of the proper resources for its dialog.  If they're there it displays its dialog; otherwise it goes ahead and prints without the dialog.  With DeleteResFork, I took a different approach--it creates a dialog without using a DITL resource for the dialog item list.
  99.  
  100. The functions AddButton, AddUserItem, and AddStatText append a new item to a dialog item list in memory.  The function MakeDITL uses these to build an item list from scratch.
  101. (Roger tells me that Tech Note #95, How To Add Items to the Print Dialogs, includes some code that handles the general case of adding an item to an item list.)
  102.  
  103. The drawback to creating a dialog item list on the fly without resources is that you can't alter the text of the dialog without recompiling the source code.  However, in the case of XCMD's it may be more valuable to be certain that a vital resource isn't missing than it is to enable alteration of titles and text without source code.
  104.  
  105. Perhaps the safest procedure is to include both the resources and the code to create them on the fly.  If the resources are present, go ahead and use them.  If not, create them on the fly.
  106.  
  107. DeleteResFork also contains a filter for ModalDialog that handles the usual keyboard equivalents for Cancel (command-period, command-q, command-Q, escape) and OK (return and enter).
  108.  
  109. Revision History:
  110. 8 June 1989, Version 1.6 -- Fixed double disposal of item list handle.
  111.  
  112. -- part contents for card part 4
  113. ----- text -----
  114. UNIT DataSaver;
  115.  
  116. { DeleteResFork XCMD ┬⌐ 1988-1989 by the Trustees of Dartmouth College }
  117. { Written by Kevin Calhoun }
  118.  
  119. { This source compatible with MPW Pascal 3.0 }
  120.  
  121. (*
  122. Pascal DeleteResFork.p
  123. Link -m ENTRYPOINT Γêé
  124.      -o "YourFile" Γêé
  125.      -rt XCMD=1659 Γêé
  126.      -sn Main=DeleteResFork Γêé
  127.      DeleteResFork.p.o Γêé
  128.     "{Libraries}"interface.o Γêé
  129.     "{PLibraries}"Paslib.o Γêé
  130.     "{Libraries}"HyperXLib.o
  131. *)
  132.  
  133. {$R-}
  134.  
  135. INTERFACE
  136.   USES
  137.     Types,
  138.     Memory,
  139.     QuickDraw,
  140.     Fonts,
  141.     Dialogs,
  142.     Files,
  143.     Resources,
  144.     Packages,
  145.     OSEvents,
  146.     ToolUtils,
  147.     HyperXCmd;
  148.  
  149.   PROCEDURE EntryPoint (paramPtr : XCMDPtr);
  150.  
  151. IMPLEMENTATION
  152.  
  153.   TYPE
  154. { for creating dialog items }
  155.     dItemPtr = ^dialogItem;
  156.     dItemHndl = ^dItemPtr;
  157.     dialogItem = RECORD
  158.         placeholder : handle;
  159.         displayRect : Rect;
  160.         typeAndDataLength : INTEGER;
  161.       END;
  162.  
  163.   PROCEDURE SaveTheData (paramPtr : XCMDPtr); FORWARD;
  164.  
  165.   PROCEDURE EntryPoint (paramPtr : XCMDPtr);
  166.   BEGIN
  167.     SaveTheData(paramPtr);
  168.   END;
  169.  
  170.   FUNCTION GetScreenBitsBounds: Rect;
  171.   { get screenbits.bounds from the QuickDraw globals }
  172.   TYPE
  173.     LongwordPtr = ^LONGINT;
  174.     BitMapPtr = ^BitMap;
  175.   CONST
  176.     screenBitsOffset = -122;
  177.     CurrentA5 = $904;
  178.   VAR
  179.     screenBitsPtr : BitMapPtr;
  180.     myLongwordPtr : LongwordPtr;
  181.   BEGIN
  182.     myLongwordPtr := LongwordPtr(CurrentA5);
  183.       { myLongwordPtr now points to the pointer to the first QD global }
  184.     myLongwordPtr := LongwordPtr(myLongwordPtr^);
  185.       { myLongwordPtr now points to the first QD global }
  186.     screenBitsPtr := BitMapPtr(myLongwordPtr^ + screenBitsOffset);
  187.       { screenBitsPtr now points to the screenBits BitMap }
  188.     GetScreenBitsBounds := screenBitsPtr^.bounds;
  189.   END;
  190.  
  191.   PROCEDURE GetEventMask (VAR theMask : INTEGER);
  192. { returns the current event mask in theMask }
  193.     CONST
  194.       SysEvtMask = $144;
  195.     TYPE
  196.       IntegerPtr = ^INTEGER;
  197.     VAR
  198.       myIntPtr : IntegerPtr;
  199.   BEGIN
  200.     myIntPtr := IntegerPtr(SysEvtMask);
  201.     theMask := myIntPtr^;
  202.   END;
  203.  
  204.   PROCEDURE CenterRect(VAR r: Rect; inRect: Rect);
  205.     VAR
  206.       hSize, vSize: INTEGER;
  207.       hCoord, vCoord: INTEGER;
  208.   BEGIN
  209.     WITH r DO
  210.       BEGIN
  211.       hCoord := left;
  212.       vCoord := top;
  213.       hSize := right-left;
  214.       vSize := bottom-top;
  215.       END;
  216.     WITH inRect DO
  217.       BEGIN
  218.       hCoord := (right-left - hSize) DIV 2 + left;
  219.       vCoord := (bottom-top - vSize) DIV 2 + top;
  220.       END;
  221.     SetRect(r, hCoord, vCoord, hCoord+hSize, vCoord+vSize);
  222.   END;
  223.  
  224.   PROCEDURE PassReturnValue (paramPtr : XCMDPtr;
  225.                   theMsg : Str255); { set theResult }
  226.   BEGIN
  227.     paramPtr^.returnValue := PasToZero(paramPtr, theMsg);
  228.   END;
  229.  
  230.   FUNCTION MyFilter (theDialog : DialogPtr;
  231.                   VAR theEvent : EventRecord;
  232.                   VAR itemHit : INTEGER) : BOOLEAN;
  233. { filter function for modal dialog -- handles the usual key equivalents for OK and Cancel }
  234.     VAR
  235.       theChar : char;
  236.       dummy : EventRecord;
  237.  
  238.     PROCEDURE PushButton (itemNo : INTEGER);
  239. { Hilites the button itemNo while a key is pressed. }
  240. { For this to work properly, the event mask must be set to allow }
  241. { keyUp events to be detected -- that's why the call to ModalDialog, }
  242. { below, is bracketed by calls to SetEventMask. }
  243.       VAR
  244.         itemType : INTEGER;
  245.         itemHandle : Handle;
  246.         itemBox : Rect;
  247.     BEGIN
  248.       GetDItem(theDialog, itemNo, itemType, itemHandle, itemBox);
  249.       HiliteControl(ControlHandle(itemHandle), inButton);
  250.       REPEAT
  251.       UNTIL OSEventAvail(keyUpMask, dummy);
  252.       HiliteControl(ControlHandle(itemHandle), 0);
  253.     END;
  254.  
  255.   BEGIN
  256.     MyFilter := FALSE;
  257.     CASE theEvent.what OF
  258.       keyDown, autoKey : 
  259.         BEGIN
  260.           theChar := CHR(BitAnd(theEvent.message, charCodeMask));
  261.           IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN
  262.             BEGIN
  263.               MyFilter := TRUE;
  264.               CASE ORD(theChar) OF
  265.                 46, 81, 113 :
  266. { if user pressed command-period, -q, or -Q, then do Cancel }
  267.                   BEGIN
  268.                     PushButton(Cancel);
  269.                     itemHit := Cancel;
  270.                     MyFilter := TRUE;
  271.                   END;
  272.               END;
  273.             END
  274.           ELSE
  275.             CASE ORD(theChar) OF
  276.               13, 3 :
  277. { if the user pressed return or enter, do OK }
  278.                 BEGIN
  279.                   PushButton(OK);
  280.                   itemHit := OK;
  281.                   MyFilter := TRUE;
  282.                 END;
  283.               27, 96 :
  284. { if user pressed the escape key or the tilde key, do Cancel }
  285.                 BEGIN
  286.                   PushButton(Cancel);
  287.                   itemHit := Cancel;
  288.                   MyFilter := TRUE;
  289.                 END;
  290.             END;
  291.         END;
  292.     END;
  293.   END;
  294.  
  295.   PROCEDURE DrawBoxAroundDefault (theWindow : WindowPtr;
  296.                   itemNo : INTEGER);
  297.     VAR
  298.       itemType : integer;
  299.       itemHdl : Handle;
  300.       itemBox : rect;
  301.   BEGIN
  302.     GetDItem(theWindow, 1, itemType, itemHdl, itemBox);
  303.     PenSize(3, 3);
  304.     InsetRect(itemBox, -4, -4);
  305.     FrameRoundRect(itemBox, 16, 16);
  306.     PenSize(1, 1);
  307.   END;
  308.  
  309.   PROCEDURE DrawVersionInfo (theWindow : WindowPtr;
  310.                   itemNo : INTEGER);
  311.     VAR
  312.       itemType : integer;
  313.       itemHdl : Handle;
  314.       itemBox : rect;
  315.       str : Str255;
  316.   BEGIN
  317.     str := 'DeleteResFork XCMD 1.6   ┬⌐1989 Dartmouth College';
  318.     GetDItem(theWindow, itemNo, itemType, itemHdl, itemBox);
  319.     TextFont(Geneva);
  320.     TextSize(9);
  321.     TextBox(POINTER(ORD(@str) + 1), LENGTH(str), itemBox, teJustLeft);
  322.     TextFont(SystemFont);
  323.     TextSize(12);
  324.   END;
  325.  
  326.   FUNCTION AddButton (boundsRect : rect;
  327.                   title : Str255;
  328.                   VAR theItems : Handle) : OSErr;
  329. { add information for a new button item to the end of the DITL theItems }
  330.     VAR
  331.       newItem : DItemHndl;
  332.       err : OSErr;
  333.   BEGIN
  334.     newItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  335.     err := MemError;
  336.     IF (newItem <> NIL) AND (err = noErr) THEN
  337.       BEGIN
  338.         MoveHHi(Handle(newItem));
  339.         HLock(Handle(newItem));
  340.         WITH newItem^^ DO
  341.           BEGIN
  342.             placeholder := NIL;
  343.             displayRect := boundsRect;  { display rectangle }
  344.             typeAndDataLength := (ctrlItem + btnCtrl) * 256 + LENGTH(title);
  345.                      { high byte contains itemType, low byte contains length of the button title }
  346.           END;
  347.         err := HandAndHand(Handle(newItem), theItems);  { copy this info into item list }
  348.         IF err = noErr THEN
  349.           err := PtrAndHand(POINTER(ORD4(@title) + 1), theItems, LENGTH(title));
  350.                { copy the characters of the title into the item list }
  351.         DisposHandle(Handle(newItem));
  352.       END;
  353.     AddButton := err;
  354.   END;
  355.  
  356.   FUNCTION AddUserItem (boundsRect : rect;
  357.                   theProc : ProcPtr;
  358.                   VAR theItems : Handle) : OSErr;
  359.     VAR
  360.       theUserItem : DItemHndl;
  361.       err : OSErr;
  362.   BEGIN
  363.     theUserItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  364.     err := MemError;
  365.     IF (theUserItem <> NIL) AND (err = noErr) THEN
  366.       BEGIN
  367.         MoveHHi(Handle(theUserItem));
  368.         HLock(Handle(theUserItem));
  369.         WITH theUserItem^^ DO
  370.           BEGIN
  371.             placeholder := Handle(theProc);
  372.             displayRect := boundsRect;
  373.             typeAndDataLength := userItem * 256 + 0;
  374.           END;
  375.         err := HandAndHand(Handle(theUserItem), theItems);
  376.         DisposHandle(Handle(theUserItem));
  377.       END;
  378.     AddUserItem := err;
  379.   END;
  380.  
  381.   FUNCTION AddStatText (boundsRect : rect;
  382.                   str : Str255;
  383.                   VAR theItems : Handle) : OSErr;
  384.     VAR
  385.       theStatTextItem : DItemHndl;
  386.       err : OSErr;
  387.   BEGIN
  388.     theStatTextItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  389.     err := MemError;
  390.     IF (theStatTextItem <> NIL) AND (err = noErr) THEN
  391.       BEGIN
  392.         MoveHHi(Handle(theStatTextItem));
  393.         HLock(Handle(theStatTextItem));
  394.         WITH theStatTextItem^^ DO
  395.           BEGIN
  396.             placeholder := NIL;
  397.             displayRect := boundsRect;
  398.             typeAndDataLength := (statText + itemDisable) * 256 + LENGTH(str);
  399.           END;
  400.         err := HandAndHand(Handle(theStatTextItem), theItems);
  401.         IF err = noErr THEN
  402.           err := PtrAndHand(POINTER(ORD4(@str) + 1), theItems, LENGTH(str));
  403.         DisposHandle(Handle(theStatTextItem));
  404.       END;
  405.     AddStatText := err;
  406.   END;
  407.  
  408.   FUNCTION MakeDITL (VAR theItems : Handle) : OSErr;
  409. { Create our dialog item list on the fly. }
  410. { We rely heavily on the information given in IM-I, p. 427 }
  411.     CONST
  412.       numItems = 6;
  413.     VAR
  414.       myStatTextItem : dItemHndl;
  415.       err : OSErr;
  416.       itemCount : INTEGER;
  417.       str : Str255;
  418.       theRect : Rect;
  419.   BEGIN
  420.     theItems := NewHandle(2);
  421. { we'll build this handle into a full item list by appending info to it }
  422. { for each item we want to add with HandAndHand and PtrAndHand }
  423.     IF theItems <> NIL THEN
  424.       BEGIN
  425.         itemCount := numItems - 1;
  426.         BlockMove(@itemCount, theItems^, 2);
  427. { first two bytes of the DITL = number of items in list minus 1 }
  428.         SetRect(theRect, 230, 100, 300, 120);
  429.         err := AddButton(theRect, 'OK', theItems);
  430.         IF err = noErr THEN
  431.           BEGIN
  432.             SetRect(theRect, 140, 100, 210, 120);
  433.             err := AddButton(theRect, 'Cancel', theItems);
  434.             IF err = noErr THEN
  435.               BEGIN
  436.                 SetRect(theRect, 220, 90, 310, 130);
  437.                 err := AddUserItem(theRect, @DrawBoxAroundDefault, theItems);
  438.                 IF err = noErr THEN
  439.                   BEGIN
  440.                     SetRect(theRect, 10, 97, 130, 125);
  441.                     err := AddUserItem(theRect, @DrawVersionInfo, theItems);
  442.                     IF err = noErr THEN
  443.                       BEGIN
  444.                         SetRect(theRect, 10, 10, 302, 50);
  445.                         str := 'Are you sure you want to delete the resource fork of: ';
  446.                         err := AddStatText(theRect, str, theItems);
  447.                         IF err = noErr THEN
  448.                           BEGIN
  449.                             SetRect(theRect, 10, 52, 302, 92);
  450.                             str := 'ΓÇ£^0ΓÇ¥? ';
  451.                             err := AddStatText(theRect, str, theItems);
  452.                           END;  { if err = noErr when creating the first statText item }
  453.                       END;  { if err = noErr when creating the version info userItem }
  454.                   END;  { if err = noErr when creating the default button userItem }
  455.               END;  { if err = noErr when creating Cancel Button }
  456.           END;  { if err = noErr when creating OK button }
  457.       END; { if theItems <> nil }
  458.     MakeDITL := err;
  459.   END;
  460.  
  461.   PROCEDURE DoSFGet (VAR SFGetReply : SFReply);
  462.     VAR
  463.       where : point;
  464.       typeList : SFTypeList;
  465.       dlgt: DialogTHndl;
  466.       r: rect;
  467.       screen: rect;
  468.       h, v: INTEGER;
  469.   BEGIN  { select text file to read using SFGetFile }
  470.     dlgt := DialogTHndl(GetResource('DLOG',getDlgID));
  471.     if dlgt <> nil then
  472.       begin
  473.       r := dlgt^^.boundsRect;
  474.       screen := GetScreenBitsBounds;
  475.       h := ((screen.right - screen.left) - (r.right - r.left)) div 2;
  476.       v := ((screen.bottom - screen.top) - (r.bottom - r.top)) div 2;
  477.       SetPt(where, h, v);
  478.       end
  479.     else SetPt(where, 82, 75);
  480.     typeList[0] := 'STAK';                { tell SFGetFile to display only text files }
  481.     SFGetFile(where, '', NIL, 1, typeList, NIL, SFGetReply);          { call SFGetFile }
  482.   END;
  483.  
  484.   FUNCTION DeleteResourceFork (fName : Str255;
  485.                   vRefNum : INTEGER) : OSErr;
  486. { delete the resource fork of a file }
  487.     VAR
  488.       theRefNum : INTEGER;
  489.       closeErr, err : OSErr;
  490.   BEGIN
  491.     err := OpenRF(fName, vRefNum, theRefNum);  { open the file }
  492.  
  493.     IF err = noErr THEN              { continue only if file could be opened }
  494.       BEGIN
  495.         err := SetEOF(theRefNum, 0);  { set the length of the resource fork to 0 }
  496.         closeErr := FSClose(theRefNum);  { close the file }
  497.       END;
  498.     DeleteResourceFork := err;
  499.   END; { procedure DeleteResourceFork }
  500.  
  501.   PROCEDURE SaveTheData (paramPtr : XCMDPtr);
  502.     VAR
  503.       err : OSErr;
  504.       SFGetReply : SFReply;
  505.       gotAFile : BOOLEAN;
  506.       theFileName : Str255;
  507.       theVRefNum : INTEGER;
  508.       fndrInfo : FInfo;
  509.       myItems : Handle;
  510.       bounds : rect;
  511.       myDialog : DialogPtr;
  512.       dStorage : Handle;
  513.       theMask : INTEGER;
  514.       itemHit : INTEGER;
  515.       numStr : Str255;
  516.  
  517.   BEGIN { procedure SaveTheData }
  518.     gotAFile := FALSE;
  519.     IF paramPtr^.paramCount < 1 THEN
  520. { user did not specify a file -- put up standard file dialog box }
  521.       BEGIN
  522.         DoSFGet(SFGetReply);
  523.         SendCardMessage(paramPtr, 'go to this card');
  524.         IF SFGetReply.good THEN
  525.           BEGIN         { continue only if user actually selected a file }
  526.             WITH SFGetReply DO
  527.               BEGIN
  528.                 theFileName := fName;
  529.                 theVRefNum := vRefNum;
  530.               END;  { with SFGetReply }
  531.             gotAFile := TRUE;
  532.           END;
  533.       END
  534.     ELSE
  535. { user specified a file -- check to see if it's really a stack }
  536.       BEGIN
  537.         ZeroToPas(paramPtr, paramPtr^.params[1]^, theFileName);
  538.         err := GetFInfo(theFileName, 0, fndrInfo);
  539.         IF (err = noErr) AND (fndrInfo.fdType = 'STAK') THEN
  540.           BEGIN
  541.             gotAFile := TRUE;
  542.             theVRefNum := 0;
  543.           END
  544.         ELSE IF err <> noErr THEN
  545.           BEGIN
  546.           NumToStr(paramPtr, err, numStr);
  547.           PassReturnValue(paramPtr, CONCAT('Error ', numStr));
  548.           END
  549.         ELSE
  550.           PassReturnValue(paramPtr, 'Error -- that file is not a stack');
  551.       END;
  552.     IF gotAFile THEN
  553.       BEGIN
  554. { create our dialog item list on the fly and put up our dialog }
  555.         err := MakeDITL(myItems);
  556.         IF err = noErr THEN
  557.           BEGIN
  558.           SetRect(bounds, 100, 80, 412, 210);
  559.           CenterRect(bounds, GetScreenBitsBounds);
  560.           ParamText(theFileName, '', '', '');
  561.           dStorage := NewHandle(SIZEOF(DialogRecord));
  562.           err := MemError;
  563.           IF dStorage <> NIL THEN
  564.             BEGIN
  565.             MoveHHi(dStorage);
  566.             HLock(dStorage);
  567.             myDialog := NewDialog(dStorage^, bounds, '', TRUE, dBoxProc, POINTER(-1), FALSE, 0, myItems);
  568.             IF myDialog <> NIL THEN
  569.               BEGIN
  570.               GetEventMask(theMask);
  571.               SetEventMask(everyEvent);
  572.               REPEAT
  573.                 ModalDialog(@MyFilter, itemHit);
  574.               UNTIL (itemHit = OK) OR (itemHit = Cancel);
  575.               SetEventMask(theMask);
  576.               CloseDialog(myDialog);
  577.               IF itemHit = OK THEN
  578.                 err := DeleteResourceFork(theFileName, theVRefNum);
  579.               END;
  580.             DisposHandle(dStorage);
  581.             END;
  582.           DisposHandle(myItems);
  583.           END;
  584.         IF err <> noErr THEN
  585.           BEGIN
  586.           NumToStr(paramPtr, err, numStr);
  587.           PassReturnValue(paramPtr, CONCAT('Error ', numStr));
  588.           END;
  589.       END; { if gotAFile }
  590.   END;
  591.  
  592. END.